class Solution {
  /**
   * returns an array containing all the numbers from start up to
   * @param start start
   * @param end end
   */
  range(start: number, end: number): Array<number> {
    let result = [];
    if (start <= end) {
      for (; start <= end; start++) {
        result.push(start);
      }
    }
    return result;
  }

  range2(start: number, end: number, step?: number): Array<number> {
    let result = [];
    if (!step) {
      step = 1;
    }
    while (start <= end) {
      result.push(start);
      start += step;
    }
    return result;
  }

  sum(arr: Array<number>): number {
    let result = 0;
    for (let n of arr) {
      result += n;
    }
    return result;
  }

  // 运行更快，因为它的基本操作是插入（O(1)）
  reverseArray(arr) {
    let result = [];
    for (let i = arr.length - 1; i >= 0; i--) {
      result.push(arr[i]);
    }
    return result;
  }

  reverseArrayPlace(arr) {
    for (let i = 0, j = arr.length - 1; i < j; i++, j--) {
      let tmp = arr[i];
      arr[i] = arr[j];
      arr[j] = tmp;
    }
  }

  arrayToList(arr) {
    let list;
    let result;
    for (let e of arr) {
      let node = {
        value: e,
        rest: null,
      };
      if (!list) {
        list = node;
        result = list;
      } else {
        list.rest = node;
        list = list.rest;
      }
    }
    return result;
  }

  listToArray(list) {
    let result = [];
    // 当列表本身为null时跳出循环
    while (list) {
      result.push(list.value);
      list = list.rest;
    }
    return result;
  }

  prepend(ele, list) {
    let result = { value: ele, rest: null };
    let newList = {};
    Object.assign(newList, list);
    result.rest = newList;
    return result;
  }

  nth(list, idx) {
    let cur = 0;
    while (cur <= idx && list) {
      if (cur++ == idx) {
        return list.value;
      }
    }
    return;
  }

  nthRecursive(list, idx) {
    while (list && idx >= 0) {
      if (idx == 0) {
        return list.value;
      } else {
        return this.nthRecursive(list.rest, idx - 1);
      }
    }

    return undefined;
  }

  deepEqual(obj1, obj2) {
    if (obj1 && obj2 && typeof obj1 == "object" && typeof obj2 == "object") {
      let o1Props = Object.keys(obj1);
      let o2Props = Object.keys(obj2);
      if (o1Props.length == o2Props.length) {
        for (let prop of o1Props) {
          if (o2Props.includes(prop)) {
            return this.deepEqual(o1Props[prop], o2Props[prop]);
          } else {
            return false;
          }
        }
      }
      return false;
    } else {
      return obj1 === obj2;
    }
  }
}

const sol = new Solution();
console.log(sol.sum(sol.range(1, 10)));
console.log(sol.sum(sol.range2(1, 10, 2)));

const arr = [1, 2, 3, 4, 5];
console.log(sol.reverseArray(arr));
console.log(arr);
sol.reverseArrayPlace(arr);
console.log(arr);

let list = sol.arrayToList(arr);
console.log(list);
console.log(sol.listToArray(list));
let otherList = sol.prepend(6, list);
console.log(sol.listToArray(otherList));
otherList.value = 9;
console.log(sol.listToArray(list));
console.log(sol.listToArray(otherList));

console.log(sol.nth(otherList, 0));
console.log(sol.nth(otherList, -1));

console.log(sol.nthRecursive(otherList, 0));
console.log(sol.nthRecursive(otherList, 6));
console.log(sol.nthRecursive(otherList, 5));
console.log(sol.nthRecursive(otherList, -1));

let o1 = null;
let o2 = undefined;
let o3 = 3;
let o4 = "str";
let o5 = false;
let o6 = true;
let o7 = 4;
let o8 = "str";
let o9 = {
  a: 1,
  b: {
    c: 3,
  },
};
let o10 = {
  c: 3,
};
let o11 = {
  a: 1,
  b: {
    c: 3,
  },
};
console.log(sol.deepEqual(o1, o2));
console.log(sol.deepEqual(o1, o1));
console.log(sol.deepEqual(o2, o2));
console.log(sol.deepEqual(o9, o10));
console.log(sol.deepEqual(o9, o11));
console.log(sol.deepEqual(o3, o7));
console.log(sol.deepEqual(o4, o8));
console.log(sol.deepEqual(o5, o6));
console.log(sol.deepEqual(o1, o5));
